﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Calendar;

using Gsn.Common;

namespace Gsn.Calendar.Engine
{
    public class CalendarServiceWrapper
    {
        private CalendarService service_;
        private String username_;

        public CalendarServiceWrapper(String username, String password)
        {
            service_ = new CalendarService(Constants.AppDescription);
            service_.setUserCredentials(username, password);

            this.username_ = username;
        }

        public CalendarFeed GetAllCalendars()
        {
            if (service_ == null)
                return null;

            try
            {
                CalendarQuery query = new CalendarQuery("http://www.google.com/calendar/feeds/default/allcalendars/full"); //"http://www.google.com/calendar/feeds/" + username_ + "/allcalendars/composite");
                CalendarFeed calendars = service_.Query(query);
                return calendars;
            }
            catch (Exception e)
            {
                ///eat up errors "quietly" :S ...
                return null;
            }   
        }

        public CalendarFeed GetOwnedCalendars()
        {
            if (service_ == null)
                return null;

            try
            {
                CalendarQuery query = new CalendarQuery("http://www.google.com/calendar/feeds/default/owncalendars/composite");
                CalendarFeed calendars = service_.Query(query);
                return calendars;
            }
            catch (Exception e)
            {
                ///eat up errors "quietly" :S ...
                return null;
            }
        }

        private EventFeed GetNEventsForCalendar(String calendarUri, int numberOfEvents)
        {
            if (service_ == null)
                return null;

            if (calendarUri == null || calendarUri.Length == 0)
                return null;

            try
            {
                EventQuery query = new EventQuery(calendarUri);
                query.NumberToRetrieve = numberOfEvents;
                query.SortOrder = CalendarSortOrder.ascending;
                EventFeed events = service_.Query(query);
                return events;
            }
            catch (Exception e)
            {
                ///eat up errors "quietly" :S ...
                return null;
            }
        }

        private EventFeed GetNMatchingEventsForCalendar(string calendarUri, DateTime fromDate, DateTime toDate, int numberOfEvents)
        {
            if (service_ == null)
                return null;

            if (calendarUri == null || calendarUri.Length == 0 || fromDate == null || toDate == null)
                return null;

            try
            {
                EventQuery query = new EventQuery(calendarUri);
                query.NumberToRetrieve = numberOfEvents;
                query.SortOrder = CalendarSortOrder.ascending;
                query.StartTime = fromDate;
                query.EndTime = toDate;
                EventFeed events = service_.Query(query);
                return events;
            }
            catch (Exception e)
            {
                ///eat up errors "quietly" :S ...
                return null;
            }
        }

        public ICollection<EventEntry> GetCollectionOfNEventsForCalendar(string calendarUri, int numberOfEvents)
        {
            List<EventEntry> events = new List<EventEntry>();

            EventFeed eventFeed = this.GetNEventsForCalendar(calendarUri, numberOfEvents);

            if (eventFeed == null)
                return null;

            foreach (EventEntry eventEntry in eventFeed.Entries)
                events.Add(eventEntry);

            return events;
        }

        public ICollection<EventEntry> GetCollectionOfNMatchingEventsForCalendar(string calendarUri, DateTime fromDate, DateTime toDate, int numberOfEvents)
        {
            List<EventEntry> events = new List<EventEntry>();

            EventFeed eventFeed = this.GetNMatchingEventsForCalendar(calendarUri, fromDate, toDate, numberOfEvents);

            if (eventFeed == null)
                return null;

            foreach (EventEntry eventEntry in eventFeed.Entries)
                events.Add(eventEntry);

            return events;
        }

        public ICollection<EventEntry> GetCollectionOfNEventsForAllCalendars(int numberOfEvents)
        {
            List<EventEntry> events = new List<EventEntry>();

            CalendarFeed calendars = this.GetAllCalendars();
            
            if (calendars == null)
                return null;

            foreach (CalendarEntry calendar in calendars.Entries)
            {
                ICollection<EventEntry> retrievedEvents = this.GetCollectionOfNEventsForCalendar(CalendarEntryHelper.GetCalendarUri(calendar), numberOfEvents);

                if (retrievedEvents == null)
                    continue;

                events.AddRange(retrievedEvents);
            }

            return events;
        }

        public ICollection<EventEntry> GetCollectionOfNMatchingEventsForAllCalendars(DateTime fromDate, DateTime toDate, int numberOfEvents)
        {
            List<EventEntry> events = new List<EventEntry>();

            CalendarFeed calendars = this.GetAllCalendars();

            if (calendars == null)
                return null;

            foreach (CalendarEntry calendar in calendars.Entries)
            {
                ICollection<EventEntry> retrievedEvents = this.GetCollectionOfNMatchingEventsForCalendar(CalendarEntryHelper.GetCalendarUri(calendar), fromDate, toDate, numberOfEvents);

                if (retrievedEvents == null)
                    continue;

                events.AddRange(retrievedEvents);
            }

            return events;
        }
    }
}
